/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2024-05-20 17:17:23
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 12:57:17
 * @FilePath     : \openchaoji-corelib\shared\include\OpenChaoJi_utility_data_buff.h
 * @Description  : 本文件定义通用数据收发模块, 用于定时发送数据和接受缓存数据队列
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */


#ifndef __OPEN_CHAOJI_UTILITY_DATA_BUFF_H__
#define __OPEN_CHAOJI_UTILITY_DATA_BUFF_H__

#include "OpenChaoJi_config.h"
#include "OpenChaoJi_type.h"
#include "OpenChaoJi_os.h"
#include "OpenChaoJi_debug.h"

/**
 * @brief 本模块的上下文数据结构
 */
struct OpenChaoJi_context_utility_data_buff;

/**
 * @brief 创建本模块的上下文时需要传入的参数
 */
struct OpenChaoJi_create_info_utility_data_buff {
	int tag;

	unsigned int recv_capacity;   		//阶段理论多包传输最大值 A类4  B类1
};

/**
 * @brief 发送数据结构体，用于组织待发送数据的参数。
 *
 * 此结构体封装了数据发送所需的配置信息，如发送间隔、数据标签及数据本身。
 */
struct OpenChaoJi_utility_data_buff_send_data
{
	//tag 用于识别或分类发送的数据, 系统统一定义, sys_type表示属于A类，B类系统，ack表示可靠消息或不可靠消息，可靠消息（如: A类长消息，B类可靠消息），
	//不可靠消息填0（如: A类短消息，B类不可靠消息），如果是A类系统收发，则tag还应填写sa,ps,pf,p信息
	union
	{
		uint32_t	all;
		struct
		{
			uint32_t sa			:8; // 原地址
	        uint32_t ps			:8; // 目的地址
			uint32_t pf			:8; // pf值
			uint32_t p			:3; // 优先级
			uint32_t ack		:1; // 0: urm   1: rm
			uint32_t data_type	:4; // 0: can数据帧      1: gbt27930_a类消息     2:gbt27930_b类消息
		}gbt;
	}tag;
                        			// 同一个tag的数据, 后到的会覆盖先到的
	int 	interval_ms;		        // 指定连续发送数据包之间的时间间隔。
	int 	cnt;			        // 数据发送最大次数，-1为一直发送

	struct multiple_data send_data; 	//发送数据
};


/**
 * @brief 接收数据结构体，用于存放接收数据接口传输的参数。
 *
 * 此结构体封装了数据接收所需的配置信息，如数据本身及数据长度
 */
struct OpenChaoJi_utility_data_buff_recv_data
{
	//uint32_t	tag;			        // TOTO: by zhaolh
	union
	{
		uint32_t	all;
		struct
		{
			uint32_t sa			:8; // 原地址
	        uint32_t ps			:8; // 目的地址
			uint32_t pf			:8; // pf值
			uint32_t p			:3; // 优先级
			uint32_t ack		:1; // 0: urm   1: rm
			uint32_t msg_type	:4; // 0: A类系统消息        1: gbt27930 B类系统链路层数据	      2:gbt27930_b类系统传输层消息
		}gbt;
	}tag;

	struct multiple_data recv_data;   //接收数据
	uint32_t 	     recv_tick;	  //该数据接收的时间戳
};

/**
 * @brief 初始化
 *
 * @param info 初始化信息
 * @return 成功返回创建的上下文指针，失败返回NULL。
 */
struct OpenChaoJi_context_utility_data_buff * OpenChaoJi_utility_data_buff_init(const struct OpenChaoJi_create_info_utility_data_buff * info);

/**
 * @brief 销毁
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_utility_data_buff_term(struct OpenChaoJi_context_utility_data_buff * context);

/**
 * @brief 复位, 清空收发缓冲区和队列
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_utility_data_buff_reset(struct OpenChaoJi_context_utility_data_buff * context);

/**
 * @brief 保存数据到队列, serivce每次运行gbt27930前会从传输层读取完整的数据包, 如果判断为给应用层的数据包则调用本方法进行暂存
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_utility_data_buff_queue_write(struct OpenChaoJi_context_utility_data_buff * context, struct OpenChaoJi_utility_data_buff_recv_data * write_data);

/**
 * @brief 从队列读取数据, gbt27930运行时, 需要从本模块的队列中读取数据, 一次读取一个包. 每次service运行会循环调用本函数读取, 直到读光.
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param recv_data 待读取数据结构, 注意读取方需要自行free接收的数据区
 * @return 读到数据返回0，读不到数据返回-1。
 */
int OpenChaoJi_utility_data_buff_queue_read(struct OpenChaoJi_context_utility_data_buff * context, struct OpenChaoJi_utility_data_buff_recv_data * recv_data);

/**
 * @brief 写入数据, gbt27930运行时, 如果需要发送数据给evcc, 则通过本方法写入发送区
 *        需要比较send_data的tag和本地发送区的tag, 如果tag相同, 则覆盖本地发送区的数据, 如果tag不同, 则将send_data插入到发送区
 *        本方法会根据send_data的interval_ms和cnt自动计算发送时间, 如果send_data的cnt为-1, 则一直发送
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param send_data 待发送的数据结构
 * @param stop_flag 设置为1时，设置cnt为0，停止发送
 * @return 读到数据返回0，读不到数据返回-1。
 */

int OpenChaoJi_utility_data_buff_data_write(struct OpenChaoJi_context_utility_data_buff * context, struct OpenChaoJi_utility_data_buff_send_data * send_data, int stop_flag) ;
/**
 * @brief 发送数据, serivce每次运行gbt27930后会再调用本方法. 本模块需要判断本地发送区的各数据是否已经到了发送时间, 如果是, 则立即调用传输层发送函数.
 *
 * @param context 系统上下文指针，包含必要的环境信息。
 * @param write_func 发送数据的方法
 * @param param write_func方法所需要的私有参数, 一般是传输层句柄
 * @return 成功返回0，失败返回-1。
 */
int OpenChaoJi_utility_data_buff_service_try_send(struct OpenChaoJi_context_utility_data_buff * context
		, int (*write_func)(void *param, struct OpenChaoJi_utility_data_buff_send_data * send_data), void * param);

#endif
